import datetime
import random
import re
from enums.sys_type_enum import SysTypeEnum
from curl_cffi import requests
import js2py
import time
from utils.common.scheduler import scheduler
import execjs
from utils.ip_proxy.pinzan_ip_proxy import PinzanHttpProxy
from urllib.parse import urlparse

session = requests.Session()


class IpProxy(object):
    def __init__(self, region):
        self.sessions = session
        self.region = region

    def get_ip_proxy(self):
        time.sleep(random.uniform(1, 5))
        r = self.sessions.get("https://share.proxy.qg.net/get?key=S0H7ZGI6&num=1&distinct=true&pool=1",
                              impersonate="chrome101")
        proxies = {}
        area = ''
        status_code = r.status_code
        if status_code == 200:
            json_data = r.json()
            if json_data.get('code') == 'SUCCESS':
                datas = json_data.get('data')
                if datas:
                    obj = datas[0]
                    area = obj.get('area')  # 区域 - "江苏省南通市",
                    # isp = obj.get('isp')  # 区域 - "isp": "电信",
                    # deadline = obj.get('deadline')  # ip可用时间截至日期 - "deadline": "2023-10-08 23:48:14"
                    # proxy_ip = obj.get('proxy_ip')  # ip地址 -  "proxy_ip": "180.121.135.48",
                    server = obj.get('server')  # ip+端口号 - "server": "180.121.135.48:35341",
                    proxy_url = "http://%(user)s:%(password)s@%(server)s" % {
                        "user": 'S0H7ZGI6',
                        "password": '916FBAA4A876',
                        "server": server,
                    }
                    proxies = {"http": proxy_url, "https": proxy_url}
        return proxies, area


class QuestionareSpider(object):
    def __init__(self, send_title_link, proxy_obj):
        self.sessions = session
        self.proxy_obj = proxy_obj
        self.title_link = send_title_link
        self.headers = {}

    def get_jqsign(self, ktimes: int, jqnonce: str):
        result = []
        b = ktimes % 10 if ktimes % 10 != 0 else 1
        for char in list(jqnonce):
            f = ord(char) ^ b
            result.append(chr(f))
        return ''.join(result)

    def get_jqpraram(self, rndnum, activityId, starttime):
        with open('./js_file/questionare_.js', 'r', encoding='utf8') as f:
            script = f.read()
        # context = js2py.EvalJs(enable_require=True)
        context = js2py.EvalJs()
        context.execute(script)
        ts = int(time.mktime(time.strptime(starttime, "%Y/%m/%d %H:%M:%S")))
        return context._0x156205(rndnum, ts, activityId)

    def get_jqpraram_v2(self, rndnum, activityId, starttime):
        with open('./js_file/questionare_.js', 'r', encoding='utf8') as f:
            script = f.read()
        context = execjs.compile(script)
        ts = int(time.mktime(time.strptime(starttime, "%Y/%m/%d %H:%M:%S")))
        result = context.call('_0x156205', rndnum, ts, activityId)
        return result

    def get_cookies(self):
        time.sleep(random.uniform(1, 5))
        self.headers[
            'X-Forwarded-For'] = f'{112}.{random.randint(64, 68)}.{random.randint(0, 255)}.{random.randint(0, 255)}'
        # response = self.sessions.get('https://www.wjx.cn/vm/' + self.shortId + '.aspx', headers=self.headers,
        #                            timeout=10, impersonate="chrome101", proxies=self.proxy_obj, allow_redirects=False)
        response = self.sessions.get(self.title_link, headers=self.headers, timeout=10, impersonate="chrome101",
                                     proxies=self.proxy_obj, allow_redirects=False)
        return response.content.decode()

    def get_params(self, content):
        cur_link = self.title_link
        parsed_url = urlparse(cur_link)
        path = parsed_url.path.strip('/')
        segments = path.split('/')
        required_string = segments[-1]
        title_short_id = required_string.split('.')[0]
        # ktimes 为鼠标移动次数
        ktimes = random.randint(57, 143) + int(random.random() * 286)
        # jqnonce = re.search(r'.{8}-.{4}-.{4}-.{4}-.{12}', content).group()
        # rndnum = re.search(r'\d{9,10}\.\d{8}', content).group()
        jqnonce = re.search(r'var jqnonce="(.+?)";', content).group(1)
        rndnum = re.search(r'var rndnum="(.+?)";', content).group(1)
        start_time = re.search(r'\d+?/\d+?/\d+?\s\d+?:\d{2}:\d{2}', content).group()
        activityId = re.search(r'activityId =(\d+);', content).group(1)
        activityId = int(activityId) ^ 2130030173
        params = {
            'shortid': title_short_id,
            'starttime': start_time,
            'submittype': 1,
            'ktimes': ktimes,
            'hlv': 1,
            'rn': rndnum,
            'jqpram': self.get_jqpraram_v2(rndnum, str(activityId), start_time),
            'nw': '1',
            'jwt': '4',
            'jpm': '83',
            't': int(time.time() * 1000),
            'jqnonce': jqnonce,
            'jqsign': self.get_jqsign(ktimes, jqnonce),
        }
        return activityId, params

    def submit(self, submitdata, sleeptime: int, ip_expired: int, pz_obj):
        """
        提交问卷
        :param submitdata: 需要提交数据
        :param sleeptime: 提交的间隔时间
        :param ip_expired: ip的过期时间
        :param pz_obj: ip池的代理对象
        :return:
        """
        content = self.get_cookies()
        params = self.get_params(content)
        self.headers.pop('X-Forwarded-For')
        url = "https://www.wjx.cn/joinnew/processjq.ashx"
        data = {'submitdata': submitdata}
        self.headers["Connection"] = 'close'  # 关闭长链接
        self.headers['Origin'] = 'https://www.wjx.cn'
        self.headers["Host"] = 'www.wjx.cn'
        self.headers['X-Requested-With'] = 'XMLHttpRequest'
        # self.headers["Referer"] = 'https://www.wjx.cn/vm/' + self.shortId + '.aspx'
        self.headers["Referer"] = self.title_link
        print('睡', sleeptime, '秒再开始发送')
        time.sleep(sleeptime)
        # 判断当前ip是否过期，如果过期重新获取一个ip并且立即发送请求
        if ip_expired < int(time.time() * 1000):
            print('ip已过期，重新获取ip')
            proxy_o, ip_res, ip_expired = pz_obj.get_proxy()
            self.proxy_obj = proxy_o
        res = self.sessions.post(url, headers=self.headers, params=params[1], data=data, timeout=10,
                                 proxies=self.proxy_obj, impersonate="chrome101", allow_redirects=False)
        pd = res.content.decode()
        return pd


def convert_data_to_submit_data(db_title_arr, db_res_arr) -> str:
    """
    将数据库中的数据转换为需要提交的结果数据
    :param db_title_arr: 题目与数据库结果的映射关系数组
    :param db_res_arr: 需要提交的答案数组
    :return:
    """
    res = ''
    for index in range(len(db_title_arr)):
        i = db_title_arr[index]
        indexes = i['data_index']
        cur_type = i['sys_type']
        s = i['title_id'] + '$'
        if len(indexes) > 1:
            if cur_type == SysTypeEnum.MULTIPLE.value:  # 多选题
                cur_s = ''
                for j in range(len(indexes)):
                    mu_arr = str(db_res_arr[indexes[j]]).split('^')
                    if mu_arr and mu_arr[0] == '1':  # 如果为1，表示需要提交这个选项
                        if cur_s != '':
                            cur_s += '|'
                        cur_s += str(j + 1)
                        if len(mu_arr) >= 2:
                            cur_s += '^' + str(mu_arr[1])
                s += cur_s
            elif cur_type == SysTypeEnum.MATRIX.value:
                for j in range(len(indexes)):
                    s += str(j + 1) + '!' + str(db_res_arr[indexes[j]])
                    if j < len(indexes) - 1:
                        s += ','
            elif cur_type == SysTypeEnum.SLIDE.value or cur_type == SysTypeEnum.RATE.value:
                cur_s = ''
                for j in range(len(indexes)):
                    if cur_s != '':
                        cur_s += '^'
                    cur_s += str(j + 1) + '!' + str(db_res_arr[indexes[j]])
                    # if j > len(indexes) - 1:
                    #     s += '^'
                s += cur_s
            elif cur_type == SysTypeEnum.SORTED.value:  # 排序题
                for j in range(len(indexes)):
                    s += str(db_res_arr[indexes[j]])
                    if j < len(indexes) - 1:
                        s += ','
            elif cur_type == SysTypeEnum.MULTIPLE_TEXT.value:  # 多项填空
                for j in range(len(indexes)):
                    s += str(db_res_arr[indexes[j]])
                    if j < len(indexes) - 1:
                        s += '^'
            elif cur_type == SysTypeEnum.MULTIPLE_MATRIX.value:  # 矩阵多选
                children = i['children']
                multiple_s = ''
                for child_index in range(len(children)):
                    child = children[child_index]
                    child_options = child['options']
                    if multiple_s != '':
                        multiple_s += ','
                    multiple_s += str(child_index + 1) + '!'
                    cur_s = ''
                    for j in range(len(child_options)):
                        mu_arr = str(db_res_arr[child_options[j]['data_index']]).split('^')
                        if mu_arr and mu_arr[0] == '1':  # 如果为1，表示需要提交这个选项
                            if cur_s != '':
                                cur_s += ';'
                            cur_s += str(j + 1)
                            if len(mu_arr) >= 2:
                                cur_s += '^' + str(mu_arr[1])
                    multiple_s += cur_s
                s += multiple_s
            elif cur_type == SysTypeEnum.MATRIX_TEXT.value:  # 矩阵填空
                cur_s = ''
                for j in range(len(indexes)):
                    if cur_s != '':
                        cur_s += '^'
                    cur_s += str(j + 1) + '!' + str(db_res_arr[indexes[j]])
                s += cur_s
            else:
                for j in range(len(indexes)):
                    s += str(db_res_arr[indexes[j]])
        else:
            s += str(db_res_arr[indexes[0]])
        if index < len(db_title_arr) - 1:
            s += '}'
        res += s
    return res


def do_submit(proxy_region: str, send_title_link: str, submitdata: str, sleep_time: int):
    # ip_o = IpProxy(region=proxy_region)
    # proxy_o, ip_res = ip_o.get_ip_proxy()  # 获取代理
    # 获取代理
    pz_obj = PinzanHttpProxy(proxy_region)
    proxy_o, ip_res, ip_expired = pz_obj.get_proxy()  # 代理对象，ip地址，当前ip过期时间
    qo = QuestionareSpider(send_title_link=send_title_link, proxy_obj=proxy_o)  # 创建问卷对象
    print(submitdata)
    res = qo.submit(submitdata, sleep_time, ip_expired, pz_obj)  # 提交
    return res, ip_res


# 定义一个函数，用于执行sleep操作
def sleep_10_seconds(args1, args2):
    submitdata = '1$1}2$1}3$1|2|3|4}4$1}5$1}6$1}7$3}8$1!1,2!2,3!4,4!5'
    sleep_time = random.randint(20, 40)
    res, ip_res = do_submit('', 'reLD2t6', submitdata, sleep_time)
    print(res)
    print(ip_res)
    print('任务', args1, '运行完成')


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    for i in range(10):
        time.sleep(0.002)  # 睡2毫秒，防止生成相同的task_id
        task_id = str('1') + '_child_' + str(int(time.time() * 1000))  # 根据时间戳(ms)作为唯一表示
        a = datetime.datetime.now() + datetime.timedelta(milliseconds=100)
        run_time = a.strftime("%Y-%m-%d %H:%M:%S.%f")  # 生成每组数据的间隔时间(秒)
        scheduler.add_job(sleep_10_seconds, 'date', run_date=run_time, id=task_id, jobstore='default', args=(i, 2))
    # 启动调度器

    print("所有方法已在后台运行")
    time.sleep(1000)
    print('程序执行结束')
    print(execjs.get().name)

# See PyCharm help at https://www.jetbrains.com/help/pycharm/

# 1$无^无^无^无}2$无}3$1!962!153!69}4$1!1;7;9;112!1;7;9;113!1;7;9;11}5$1!无^2!无

# 1$A^30^138^10}2$B}3$1!7^2!16^3!25}4$1!1;2;3,2!2;3,3!1;2;3;4}5$1!waiguan1^2!gongneng1
